/*
 * Created on Oct 25, 2007
 * 
 */

package com.probiz.estore.webapp.action;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.ModelAndView;

import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.common.util.DateUtil;
import com.probiz.estore.content.service.UploadManager;
import com.probiz.estore.core.controller.BaseController;
import com.probiz.estore.webapp.util.RequestUtil;

public class UploadController extends BaseController {
	public class FileInfo {
		private final static String	DEFAULT_CATEGORY	= "others";
		private String				category			= DEFAULT_CATEGORY;
		private String				fileNameOnly;
		private String				generatedPath;

		private String				suffix				= null;

		private String				url;

		public FileInfo(String category, String fileName) {
			if (category != null && !"".equals(category.trim())) {
				this.category = category;
			}
			int idx = fileName.lastIndexOf(".");
			if (idx > 0 && idx != fileName.length()) {
				suffix = fileName.substring(idx + 1, fileName.length())
						.toLowerCase();
				this.fileNameOnly = fileName.substring(0, idx);
			} else {
				this.fileNameOnly = fileName;
			}
		}

		public String appendSuffix(String suffix2) {
			StringBuilder sb = new StringBuilder(fileNameOnly);
			if (suffix2 != null && suffix2.trim().length() > 0) {
				sb.append("_").append(suffix2);
			}
			sb.append(".").append(suffix);
			return sb.toString();
		}

		public void autoRename() {
			//fileNameOnly = fileNameOnly + "_"+ UUID.randomUUID().getLeastSignificantBits();
			fileNameOnly = ""+UUID.randomUUID().getLeastSignificantBits();
			generatedPath = null;
			url = null;
		}

		public String getFileName() {
			return new StringBuilder(fileNameOnly).append(".").append(suffix)
					.toString();
		}

		public String getGeneratedPath() {
			// 可能可以考虑加上用户的id进一步减少一级目录下的文件数
			if (generatedPath == null) {
				generatedPath = new StringBuilder(category).append("/").append(
						DateUtil.getShortDateString()).append("/").toString();
			}
			return generatedPath;
		}

		public String getRelativePathAndName() {
			return getRelativePathAndName(getFileName());
		}

		public String getRelativePathAndName(String fileName) {
			return new StringBuilder(getGeneratedPath()).append(fileName)
					.toString();
		}

		public String getSuffix() {
			return suffix;
		}

		public String getUrl() {
			if (url == null) {
				url = getUrl(getFileName());
			}
			return url;
		}

		public String getUrl(String fileName) {
			String mediaCategorySimpleStr = ConfigUtil.getInstance().getMediaCategorySimple();
			if(!mediaCategorySimpleStr.equals("")){
				//例如admin,则必须加上/ 
				mediaCategorySimpleStr += "/";
			}
			return new StringBuilder(mediaCategorySimpleStr).append(getGeneratedPath()).append(encodeUrl(fileName)).toString();
		}
	}


	private UploadManager uploadManager;

	private long							maxImageSize		= 100 * 1024;

	private long							maxUploadSize		= 100 * 1024 * 1024;

	private MultipartResolver				multipartResolver;

	

	/**
	 * 保存上传的文件并返回资源的URL。可支持多个，但目前的使用方式都是一个。可支持中文文件名。可支持分类别存放。类别下会再按日期存放。
	 * 如果同一天内同名文件已经存在，会自动改名。
	 * 
	 * 
	 * 配合ocupload.js暂时只能支持每一次upload上传一个文件
	 * 
	 * 
	 * @param request
	 * @param response
	 * @return
	 * 特别注意：如果上传的文件字节为0则解释不到，不能上传成功！
	 */
	public ModelAndView defaultAction(HttpServletRequest request,
			HttpServletResponse response) {
		Map<String, Object> model = new HashMap<String, Object>();
		List<String> uploadedFiles = new ArrayList<String>();
		MultipartHttpServletRequest fileRequest = null;
		String uploadMsg = "";
		String filePath = null;
		if (multipartResolver.isMultipart(request)) {
			
			try {
				fileRequest = multipartResolver.resolveMultipart(request);
				Iterator<String> iter = fileRequest.getFileNames();
				while (iter.hasNext()) {
					String prmName = iter.next();
					MultipartFile file = fileRequest.getFile(prmName);
					if (file.isEmpty()) {
						continue;
					}
					String uploadCategory = request.getParameter("uploadCategory");
					if (uploadCategory != null
							&& uploadCategory.equalsIgnoreCase("image")
							&& file.getSize() > maxImageSize) {
						uploadMsg = "err001";
						continue;
					} else if (file.getSize() > maxUploadSize) {
						uploadMsg = "err001";
						continue;
					}
					String fileName = file.getOriginalFilename();
					FileInfo fileInfo = new FileInfo(uploadCategory, fileName);
					File pfile = null;
					boolean fileExists = false;
					do {
						fileInfo.autoRename();
						filePath = getFullFilePath(fileInfo
								.getRelativePathAndName());
						pfile = new File(filePath);
						fileExists = pfile.exists();
						if (pfile.exists()) {
							logger.info(formatMsg(
									"File already exists: %1, auto rename...",
									filePath));
							fileInfo.autoRename();
						}
					} while (fileExists);
					pfile.mkdirs();                    
					file.transferTo(pfile);
					// 处理缩放和水印，并删除原文件
					uploadManager.processImage(pfile, uploadCategory) ;
					// 不管什么情况下，都只返回原图的url就可以。
					uploadedFiles.add(fileInfo.getUrl());
				}
			} catch(MaxUploadSizeExceededException maxUploadSizeExceededException){
				uploadMsg = "err001";
				logger.error(this, maxUploadSizeExceededException);
			}catch (Throwable ex) {
			    uploadMsg = "err002";
				logger.error(formatMsg("Unexpected error when handling uploaded file %1, cause is: %2.",
		                        filePath, ex.getMessage()), ex);
			} finally {
				if (fileRequest != null) {
					multipartResolver.cleanupMultipart(fileRequest);
				}
			}
		} else {
		    uploadMsg = "err002";
			logger.warn("Invalid request, MultipartHttpServletRequest expected, found: "
		                    + request.getClass().getName()
		                    + ".\n"+ RequestUtil.getRequestInfo(request));
		}
		model.put("fileInputId",request.getParameter("fileInputId"));
		model.put("uploadedFiles", uploadedFiles);
		model.put("uploadMsg", uploadMsg);
		model.put("onCompleteHandler",request.getParameter("onCompleteHandler"));
		//针对kindeditor返回jsonMap
		String mv="";
		String mediaViewShortPath=ConfigUtil.getInstance().getMediaViewShortPath();
		String resultMv=request.getParameter("resultMv");
		if(null!=resultMv&&!"".equals(resultMv)){
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("error", 0);
			data.put("url", mediaViewShortPath+"/"+uploadedFiles.get(0));		
			JSONObject jsonMap = JSONObject.fromObject(data);
			model.put("jsonMap", jsonMap);
			mv="content/"+resultMv;
		}else{
			mv="content/uploadResults";
		}
		
		if(RequestUtil.getParameterNullSafe(request, "returnJSON").equals("true")){
			//多文件上传 newUpload
        	return this.getModelAndAjaxJsonView(model);
        }else{
			 return new ModelAndView(mv, model);
        }
	}

	protected String encodeUrl(String fileName) {
		/*try {
			return URLEncoder.encode(fileName, Constants.DEFAULT_ENCODING);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Unexpected exception!", e);
		}*/
		//目前tomcat等都已配URIEncoding 因此上传的文件名不再encode
		return fileName;
	}

	protected String getFullFilePath(String relativePath) {
		return new StringBuilder(ConfigUtil.getInstance().getMediaUploadPath()).append("/").append(
				relativePath).toString();
	}


	protected boolean isImage(String suffix) {
		return "jpg".equals(suffix) || "gif".equals(suffix);
	}

	protected boolean requireScaling(String category, String suffix) {
		// return "jpg".equals(suffix) &&
		return false;
	}

	public void setMultipartResolver(MultipartResolver multipartResolver) {
		this.multipartResolver = multipartResolver;
	}
	
	public void setUploadManager(UploadManager avalue)
	{
		uploadManager = avalue;
	}

}
